# 面向对象模块化编程
from django.contrib.messages.context_processors import messages
from django.http import JsonResponse, StreamingHttpResponse
from matplotlib.pyplot import summer

from .Qwen  import Qwen
# 导入配置文件
from django.conf import settings
# 导入模型
from .models import Topics,Chat
import requests

gen_kwargs = {
    "max_tokens": 4096,  # 生成的最大长度
    "temperature": 0.7,  # 生成丰富性，越大越有创造力 越小越确定
    "top_p": 0.8,  # 采样时的前P个候选词，越大越随机
    "extra_body": {
        "do_sample": True,  # 是否使用概率采样
        "top_k": 50,  # 采样时的前K个候选词，越大越随机
        "repetition_penalty": 1.2,  # 重复惩罚系数，越大越不容易重复
    }
}
qwen = Qwen(
            host=settings.VLLM_CONFIG.get('host'),
            model=settings.VLLM_CONFIG.get('model'),
            gen_kwargs=gen_kwargs
        )
# requests请求地址
requests_base_url=settings.VLLM_CONFIG.get('host')+ "/tokenize"

# 调用tokenize
def deltopic(request):
    """
    删除指定主题及其关联的所有聊天记录。

    参数:
        request (HttpRequest): HTTP请求对象，GET参数中应包含topic_id。

    返回:
        JsonResponse: 包含操作结果的状态码和消息。
    """
    topic_id = int(request.GET.get("topic_id", "0"))
    # # 删除主题
    # Topics.objects.filter(id=topic_id).delete()
    # # 删除对话内容
    # Chat.objects.filter(topic_id=topic_id).delete()
    # 逻辑删除
    Topics.objects.filter(id=topic_id).update(status=0)
    data = {
        "code": 200,
        "msg": "OK",
    }
    return JsonResponse(data)


# 定义第一个视图函数
'''
request:该参数表示请求对象,封装了所有的请求信息
'''
def chathistory(request):
    """
    获取指定主题下的所有聊天历史记录。

    参数:
        request (HttpRequest): HTTP请求对象，GET参数中应包含topic_id。

    返回:
        JsonResponse: 包含聊天历史记录的数据响应。
    """
    # 去接收客户端提交上来的主题ID
    topic_id = int(request.GET.get("topic_id", "0"))
    # 获取主题下面的聊天内容
    chats = Chat.objects.filter(topic_id=topic_id).order_by("id")
    history = []
    for item in chats:
        history.append(
            {
                "role": item.role,
                "content": item.content,
            }
        )

    data = {
        "code": 200,
        "msg": "OK",
        "data": history,
    }
    return JsonResponse(data, safe=False)
def _truncate_messages(messages, max_tokens_len=4096):
    """
    截断消息列表以控制总token长度，避免超出模型最大上下文长度限制。

    参数:
        messages (list): 包含对话历史的消息列表，每个元素为包含role和content的字典。
        max_tokens_len (int): 最大允许的token数量，默认为4096。

    返回:
        list: 截断后的消息列表，保留最近的对话内容。
    """
    current_tokens_len = 0

    temp = [
        {"role": "system", "content": "你是我的AI助手"}
    ]
    for msg in reversed(messages[1:]):
        # current_tokens_len += len(msg["content"] * 0.6)  #高效
        resp = requests.post(
            requests_base_url,
            json={
                "prompt": msg["content"],
            }
        )
        print(type(resp.json()))
        current_tokens_len += resp.json()["count"]
        if current_tokens_len > max_tokens_len:
            break
        temp.insert(1, msg)
    return  temp





def ai_chat_123(request):
    """
    处理AI聊天请求，支持流式输出响应。

    参数:
        request (HttpRequest): HTTP请求对象，POST参数中应包含question，GET参数中可包含topic_id。

    返回:
        StreamingHttpResponse: 流式响应对象，用于实时传输AI生成的内容。
    """
    # 接收客户端提交上来的数据
    question = request.POST.get("question", "")

    print("用户的问题：", question)
    messages = [
        {"role": "system", "content": "你是我的AI助手"},
        # {"role": "user", "content": question},
    ]

    # 去接收客户端提交上来的主题ID
    topic_id = int(request.POST.get("topic_id", '0'))
    # 保存：对话的主题，新的，就是 topic_id=0
    if topic_id == 0:
        summary = question
        if len(question)>40:
            summary = qwen.inference([
                {"role": "system", "content": "你是一个助手"},
                {"role": "user", "content": f'请根据下面的内容生成40字的摘要信息,不需要推理,直接生成: \n\n  {question}'}
            ])
        topic1 = Topics(title = question,summary=summary.split('</think>')[-1][:40], user_id = 6)
        topic1.save()
        topic_id = topic1.id
        print('新增的主题主键ID：', topic_id)
    # 不等于0,获取旧的对话内容,实现多轮对话
    else:
        chats = Chat.objects.filter(topic_id=topic_id).order_by("id")

        for item in chats:
            messages.append(
                {
                    "role": item.role,
                    "content": item.content if item.role == 'user' else item.content.strip('</think>')[-1]

                }
            )
    # 用户的问题
    messages.append({"role": "user", "content": question})
    # 控制token
    messages = _truncate_messages(messages)


    # 创建一个流式响应
    response_data = qwen.inference(messages, True)

    # 保存：对话的内容
    chat1 = Chat(content = question, topic_id = topic_id, user_id = 6, role='user')
    chat1.save()
    print('新增的聊天主键ID：', chat1.id)

    # 流式
    def event_stream():
        """
        生成SSE事件流，用于实时传输AI响应内容。

        返回:
            generator: 生成器对象，逐块产生响应数据。
        """
        try:
            # 响应主题的id到客户端
            yield "data: <topic_id__IGCV>" + str(topic_id) + "</topic_id__IGCV>\n\n"
            content = ''
            for chunk in response_data:  # 流式
                if chunk.choices:
                    delta = chunk.choices[0].delta
                    # 打印delta原始信息
                    # print("内容块：", delta)
                    if delta and delta.content:
                        # SSE 协议要求：必须以 "data:" 开头，以两个换行结尾
                        content += delta.content
                        escaped = delta.content.replace('\n', '\\n')
                        yield f'data: {escaped}\n\n'
            # 记录大模型回答的内容
            chat2 = Chat(content = content, topic_id = topic_id, user_id = 6, role='assistant')
            chat2.save()
            print('新增的LLM主键ID：', chat2.id)
        except Exception as e:
            print("错误：", e)
        finally:
            yield "data: [DONE]\n\n"

        # 结束标记


    response = StreamingHttpResponse(event_stream(), content_type="text/event-stream")
    # 设置缓存控制：只要有yield产生的数据，就立即响应到客户端，不要缓存
    response["Cache-Control"] = "no-cache"
    response["X-Accel-Buffering"] = "no"  # 禁止 Nginx 缓冲
    return response



def chatlist(request):
    """
    获取用户的聊天主题列表。

    参数:
        request (HttpRequest): HTTP请求对象。

    返回:
        JsonResponse: 包含用户聊天主题列表的数据响应。
    """
    # 假设一个用户
    user_id = 6
    history = Topics.objects.filter(user_id=user_id, status=1).order_by("-id")
    chatlist = []
    # 把数据放到列表中
    for item in history:
        chatlist.append(
            {
                "id": item.id,
                "title": item.summary,
            }
        )

    data = {
        "code": 200,
        "msg": "OK",
        "data": chatlist,
    }

    return JsonResponse(data, safe=False)
